import { IPageInfo, IPagination } from 'components/organisms/dataset/table';
import { IChat, IPrompt } from 'state/chat';
import { IDatasetFilters } from 'state/dataset';
import { IMessageElement } from 'state/element';
import { IMember, Role } from 'state/user';
import axios from 'axios'
// 导入crypto-js库
import CryptoJS from 'crypto-js';

// const devServer = 'http://139.9.232.53:7101';//后端服务地址
// const devServer = 'http://139.9.232.53:7229';//后端服务地址
const devServer = 'https://fastagi-cloud.deepexi.com';//后端服务地址
const digitalServer = 'https://www.luanshengyuzhou.com'//数字人api地址
export const digitalIframeUrl123 = "http://122.9.39.76:80/";//数字人页面地址1
export const digitalIframeUrl124 = "http://122.9.39.76:82/";//数字人页面地址2
// export const digitalIframeUrl125 = "http://123.60.182.252/";//数字人页面地址3
export const digitalIframeUrl125 = "http://122.9.39.76:83/";//数字人页面地址3横屏
// export const digitalIframeUrl123 = "http://122.9.39.76:81/digital?shuziren=123&conversation_id=331adc9b-c0c1-4217-92f5-e9decbbfc010/";//数字人页面地址
// export const digitalIframeUrl124 = "http://122.9.39.76:81/digital?shuziren=124&conversation_id=69d89087-644c-4010-9af9-e15ed34c8607/";//数字人页面地址
// export const wsEndpoint = "ws://127.0.0.1:8080";//收声api
// export const wsEndpoint = "ws://139.9.232.53:9002/ws";//横版数字人收声api
export const wsEndpointNew = 'ws://127.0.0.1:6533'
// export const wsEndpointNew = "ws://122.9.39.76:8089";//测试时使用的收声api
export const wsEndpoint_rizhi = "ws://122.9.39.76:8089";//添加日志收声api
const url = devServer;
// const conversation_id_const = 'e7be75e3-1e48-4812-b0d4-91f992cbabac' //大模型的会话id
// const conversation_id_const1 = '331adc9b-c0c1-4217-92f5-e9decbbfc010' //大模型的会话id 1
// const conversation_id_const2 = '69d89087-644c-4010-9af9-e15ed34c8607' //大模型的会员id 2
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
const shuzirenId= urlParams.get('shuziren')?? '123';// 数字人的id
const conversation_id_const= urlParams.get('conversation_id')?? '331adc9b-c0c1-4217-92f5-e9decbbfc010'
const serverUrl = new URL(url);

export const httpEndpoint = `${serverUrl.protocol}//${serverUrl.host}`;


export class ClientError extends Error {
  detail?: string;

  constructor(message: string, detail?: string) {
    super(message);
    this.detail = detail;
  }

  toString() {
    if (this.detail) {
      return `${this.message}: ${this.detail}`;
    } else {
      return this.message;
    }
  }
}

export class ChainlitClient {
  public headers: Headers;

  constructor() {
    this.headers = new Headers({
      'content-type': 'application/json'
    });
  }

  setAccessToken = (accessToken: string) => {
    this.headers.set('Authorization', accessToken);
  };

  static getProjectSettings = async () => {
    const res = await fetch(`${httpEndpoint}/project/settings`, {
      headers: {
        'content-type': 'application/json'
      },
      method: 'GET'
    });

    return res.json();
  };

  fetch = async (resource: string, options: RequestInit) => {
    const res = await fetch(`${httpEndpoint}${resource}`, {
      ...options,
      headers: this.headers
    });

    if (!res.ok) {
      let err: ClientError;
      try {
        const body = await res.json();
        err = new ClientError(res.statusText, body.detail);
      } catch (_) {
        err = new ClientError(res.statusText);
      }
      throw err;
    }
    return res;
  };

  fetch2 = async (resource: string, options: RequestInit) => {
    const res = await fetch(`${digitalServer}${resource}`, {
      ...options,
      headers: {
         'content-type':"charset=UTF-8"
      }
    });

    if (!res.ok) {
      let err: ClientError;
      try {
        const body = await res.json();
        err = new ClientError(res.statusText, body.detail);
      } catch (_) {
        err = new ClientError(res.statusText);
      }
      throw err;
    }
    return res;
  };

  getCompletion = async (
    prompt: IPrompt,
    userEnv = {},
    controller: AbortController,
    tokenCb: (done: boolean, token: string) => void
  ) => {
    const response = await this.fetch(`/completion`, {
      method: 'POST',
      signal: controller.signal,
      body: JSON.stringify({
        prompt: prompt,
        userEnv
      })
    });

    const reader = response.body?.getReader();

    const stream = new ReadableStream({
      start(controller) {
        function push() {
          reader!
            .read()
            .then(({ done, value }) => {
              if (done) {
                controller.close();
                tokenCb(done, '');
                return;
              }
              const string = new TextDecoder('utf-8').decode(value);
              tokenCb(done, string);
              controller.enqueue(value);
              push();
            })
            .catch((err) => {
              controller.close();
              tokenCb(true, '');
              console.error(err);
            });
        }
        push();
      }
    });

    return stream;
  };

  // 获取当前时间戳(毫秒)
  getCurrentTimestamp() {
    return Date.now().toString();
  }

  //获取签名
  getSignature(app_id: string, secret_key: string, timestamp: string) {
    /**
   * 生成请求签名
   * 
   * 参数:
   * app_id: 应用的 APP_ID
   * secret_key: 应用的 APP_KEY
   * timestamp: 当前时间戳，精确到毫秒
   * 
   * 返回:
   * 请求签名 (string)
   */
    const message = `${app_id}${timestamp}`;
    // 使用crypto-js实现HMAC-SHA256
    return CryptoJS.HmacSHA256(message, secret_key).toString(CryptoJS.enc.Hex);
  }

  // 调用大模型数据1！！！
  getLLMData = async (
    prompt: any,
    tokenCb: (done: boolean, token: string) => void
  ) => {
    // const response = await this.fetch(`/rag/stream_log`, {
    //   method: 'POST',
    //   body: JSON.stringify({
    //     input: {
    //       question: prompt,
    //       conversation_id: conversation_id_const
    //     },
    //     config: {}
    //   })
    // });
    const timestamp = this.getCurrentTimestamp();
    // const timestamp = '1746781411489'
    const app_id = 'f2e63623-743a-4973-b0a8-a4935f4df053';
    const secret_key = '7gnxWiY-RLUcIRQaT23tcXzkIgDl3Eag1lp93tkynYo';
    // 生成签名
    const signature = this.getSignature(app_id, secret_key, timestamp);
    const response = await fetch(
      `${devServer}/api/openapi/chat/chat-messages`,
      {
        method: 'POST',
        headers: {
          Authorization: 'Bearer app-ReXv6xkBTnomFUaqwEfcPAlY',
          'Content-Type': 'application/json',
          'app_id': app_id,
          'signature': signature,
          'timestamp': timestamp
        },
        body: JSON.stringify({
          query: prompt,
          response_mode: "streaming",
          inputs: {},
          user: "admin",
          agent_id: "f552544a-72e4-5008-bcaf-bf8382125175"
        })
      }
    );


    const reader = response.body?.getReader();
    let streamController;
    const stream = new ReadableStream({
      start(controller) {
        streamController = controller;
        function push() {
          reader!
            .read()
            .then(({ done, value }) => {
              if (done) {
                controller.close();
                tokenCb(done, '');
                return;
              }
              const string = new TextDecoder('utf-8').decode(value, { stream: true });
              tokenCb(done, string);
              controller.enqueue(value);
              push();
            })
            .catch((err) => {
              controller.close();
              tokenCb(true, '');
              console.error(err);
            });
        }
        push();
      }
    });

    return streamController;
  };

  getRole = async () => {
    const res = await this.fetch(`/project/role`, {
      method: 'GET'
    });

    const role = await res.text();
    return role as Role;
  };

  setHumanFeedback = async (messageId: string, feedback: number) => {
    await this.fetch(`/message/feedback`, {
      method: 'PUT',
      body: JSON.stringify({ messageId, feedback })
    });
  };

  getCurrentDateTime() {
    const now = new Date();
    const year = now.getFullYear();
    const month = (now.getMonth() + 1).toString().padStart(2, '0');
    const day = now.getDate().toString().padStart(2, '0');
    const hours = now.getHours().toString().padStart(2, '0');
    const minutes = now.getMinutes().toString().padStart(2, '0');
    const seconds = now.getSeconds().toString().padStart(2, '0');
    return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
  }

  // 触发数字人1！！！
  setAISay = async (txt: string, status: string, socket: Object) => {
    //  axios.get(
    //   digitalServer+`/streamllm?id=${shuzirenId}&text=${txt}&status=${status}`,
    //  {
    //   headers: {
    //       'content-type': 'application/json;utf-8',
    //   }
    //  }
    //  ).then(res => {
    //   if (socket) {
    //     socket.send('数字人ID:'+urlParams.get('shuziren')+' 持续触发数字人播报时间：'+this.getCurrentDateTime() + '，内容：'+txt); // 发送一条日志消息
    //    }
    // });
    socket.send(`{text: "${txt}", status: "${status}"}`);


    //  this.fetch2('/streamllm',{
    //   method: 'POST',
    //   body:JSON.stringify({
    //      id:'123123123',
    //      content:{
    //       text:'测试',
    //       status:'stream_token'
    //      }
    //   })
    // })

    //  axios.get('https://blog.csdn.net/phoenix/web/v1/get-novice-period-info' );
  };

  getProjectMembers = async (): Promise<IMember[]> => {
    const res = await this.fetch(`/project/members`, {
      method: 'GET'
    });
    return res.json();
  };

  getConversations = async (
    pagination: IPagination,
    filter: IDatasetFilters
  ): Promise<{
    pageInfo: IPageInfo;
    data: IChat[];
  }> => {
    const res = await this.fetch(`/project/conversations`, {
      method: 'POST',
      body: JSON.stringify({ pagination, filter })
    });

    return res.json();
  };

  getConversation = async (conversationId: string): Promise<IChat> => {
    const res = await this.fetch(`/project/conversation/${conversationId}`, {
      method: 'GET'
    });

    return res.json();
  };

  getElement = async (
    conversationId: number | string,
    elementId: number | string
  ): Promise<IMessageElement> => {
    const res = await this.fetch(
      `/project/conversation/${conversationId}/element/${elementId}`,
      {
        method: 'GET'
      }
    );

    return res.json();
  };

  deleteConversation = async (conversationId: number) => {
    const res = await this.fetch(`/project/conversation`, {
      method: 'DELETE',
      body: JSON.stringify({ conversationId })
    });

    return res.json();
  };

  getLLMProviders = async () => {
    const res = await this.fetch(`/project/llm-providers`, {
      headers: {
        'content-type': 'application/json'
      },
      method: 'GET'
    });

    return res.json();
  };

  getSpeechToText = async (formData: any) => {
    const res = await fetch(
      `https://fastagi-cloud.deepexi.com/api/voice-to-text`,
      {
        method: 'POST',
        body: formData
      }
    );

    return res.json();
  };
}
